//  iStetho3 Audio rounting to using codec 
//
//


#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_filter.h"
#include "esp_adc/adc_cali.h"
#include "adc_cali_schemes.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_sleep.h"
#include "iStetho3_util.h"
#include "u8g2_esp32.h"

extern char  devSN[5];

#define DEFAULT_VREF 3300	//Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_BAT_SAMPLES 16 //Multisampling
static const adc_channel_t channel = ADC_CHANNEL_3; //GPIO3
static const adc_atten_t atten = ADC_ATTEN_DB_12;
static const adc_unit_t unit = ADC_UNIT_1;
static esp_adc_cal_characteristics_t *bat_adc_chars;

static void check_efuse()
{
	//Check TP is burned into eFuse
	if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK)
	{
		printf("eFuse Two Point: Supported\n");
	}
	else
	{
		printf("eFuse Two Point: NOT supported\n");
	}

	//Check Vref is burned into eFuse
	if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK)
	{
		printf("eFuse Vref: Supported\n");
	}
	else
	{
		printf("eFuse Vref: NOT supported\n");
	}
}

void adc_init()
{
    check_efuse();
	adc1_config_width(ADC_WIDTH_BIT_12);
	adc1_config_channel_atten(channel, atten);
	//Characterize ADC
	bat_adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
	esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, bat_adc_chars);
}

void bat_measure(uint8_t *strVoltMsg)
{
	//static double bat_voltx[4] = { 0.0 };
	//static int bat_volty[4] = { 0 };
    uint8_t batmsg[10] = {0xAA, 0x55, 0x35, 0x05};
	uint32_t adc_reading = 0;
	float    vol = 0.0;

	//Multisampling
	for (int i = 0; i < 4; i++)
	{
		adc_reading += adc1_get_raw((adc1_channel_t)channel);
		vTaskDelay(0);						
	}
	//adc_power_release();

	adc_reading /= 4;
	//Convert adc_reading to voltage in mV
	int voltage = esp_adc_cal_raw_to_voltage(adc_reading, bat_adc_chars)*2;
	vol = voltage / 1000.0;
    sprintf((char*)(batmsg+4), "%5.3f", vol);
	ESP_LOGI("bat_measure", "Voltage : %05.3F", vol);
    memcpy(strVoltMsg, batmsg, 10);
}

void get_sysConfig(){
    nvs_handle nvsHandle;
	int8_t res = ESP_OK;
    uint8_t tVar = 0;

	// ESP_LOGI(TAG, "default sysConfig: %02X, %02X, %02X, %02X; %02x; %s\n", preGain, micPGA, ADCVolume, DACVolume, gLED_LIGHT, devSN);

	res = nvs_open("setting", NVS_READWRITE, &nvsHandle);
	if (res != ESP_OK) { 
		nvs_close(nvsHandle);
		return;
	}

	res = nvs_get_u8(nvsHandle,"volume",&tVar);
	if (res != ESP_OK) { 
	} else g_volume = tVar;

	res = nvs_get_u8(nvsHandle,"mode",&tVar);
	if (res != ESP_OK) { 
	} else g_mode = tVar;

    size_t iLen = 20;
    char  tDevSerial[20] = "";
    res = nvs_get_str(nvsHandle,"devSerial", tDevSerial, &iLen);
	if (strlen(tDevSerial) == 4) {
		strcpy(devSN, tDevSerial);
	}

	ESP_LOGI("get_sysConfig", "Restore sysConfig: volume: %d; mode: %d; BLE_sn: %s.", g_volume, g_mode, devSN);

    nvs_close(nvsHandle);
}

void set_sysConfig(){
    nvs_handle nvsHandle;
	int8_t res = ESP_OK;

    res = nvs_open("setting", NVS_READWRITE, &nvsHandle);
	if (res != ESP_OK) { 
		nvs_close(nvsHandle);
		return;
	}

    nvs_erase_key(nvsHandle,"volume");
	nvs_set_u8(nvsHandle, "volume",g_volume);

    nvs_erase_key(nvsHandle,"mode");
	nvs_set_u8(nvsHandle, "mode",g_mode);

	nvs_erase_key(nvsHandle,"devSerial");
    res = nvs_set_str(nvsHandle,"devSerial", devSN);

	ESP_LOGI("set_sysConfig", "New sysConfig: volume: %d; mode: %d, BLE_sn: %s.", g_volume, g_mode, devSN);
	nvs_close(nvsHandle);
}

